package models;

import javax.persistence.*;

import play.data.validation.*;

import java.sql.*;
import java.sql.Date;
import java.util.*;

import play.db.jpa.Model;

@Entity
public class Topic extends Model {

	@OneToMany (mappedBy = "relatedTopic", cascade=CascadeType.ALL)
	public List<Role> roles;
	@Required
	private String status; // describes whether a Topic is opened or closed
	/**
	 * @author Nader Alexan The relationship between User and Topic is
	 *         Many-To-Many. Thus, we need the following linkedlist
	 */
	@ManyToMany (mappedBy="topicList", cascade=CascadeType.ALL)
	private List<User> members;
	@Required
	private String title;
	@Required
	private String content;
	@Required
	private Date dateCreated;
	// Relationship #1 Belongs_to between Topic And Organization
	@Required
	@ManyToOne
	private Organization organization;
	@Required
	@OneToMany (mappedBy = "topic", cascade=CascadeType.ALL)
	private List<Idea> ideas;
	// Relationship #3 Manage between Topic And User
	// @ManyToOne
	// Relationship #4 Follow between Topic And Users_IK
	// on cascade is needed here
	// @ManyToMany
	// (mappedBy = "Topic", cascade = CascadeType.ALL)

	// Relationship #5 Has between Topic And Entity_IK
	// on cascade is needed here
	@Required
	@ManyToOne
	private Eentity entity;
	// Relationship #6 RelatedTo between Topic And Item_IK
	// on cascade is needed here
	@Required
	@OneToMany (mappedBy = "topic", cascade=CascadeType.ALL)
	private List<Item> items;
	// Relationship #7 Has between Topic And Comment_IK
	// on cascade is needed here
	@Required
	@OneToMany (mappedBy = "topic", cascade=CascadeType.ALL)
	private List<Comment> comments;

	// Relationship #8 RelatedTo between Topic And Tag_IK
	// on cascade is needed here for the topic model
	@Required
	@ManyToMany (mappedBy = "taggedTopics", cascade=CascadeType.ALL)
	private List<Tag> tags;
	@Required
	boolean promotedForExecution;// We need this flag to know if the Topic is
	// Promoted for Execution or not
	@Required
	private boolean spam ;
	

	/**
	 * @author mohamed elshikh
	 * List of all the relations that the topic involved in
	 */
	private LinkedList<Relationship> relations;
	/**
	 * @author mohamed elshikh
	 * add a relationship
	 */
	public void addrelationship(Relationship relation)
	{
		relations.add(relation);
	}

	/**
	 * Contstructor
	 * 
	 * @author Ibrahim Kessba
	 * @version 2011.0424
	 * @category C2 Modles
	 * @return None Number of Relations: 8
	 */

	public Topic() {
		setIdeas(new LinkedList<Idea>());
		setItems(new LinkedList<Item>());
		setComments(new LinkedList<Comment>());
		setTags(new LinkedList<Tag>());
		setMembers(new LinkedList<User>());
		promotedForExecution = false;
	}
	public LinkedList<Relationship> getRelations()
	{
		return relations;
	}

	public Topic(User initiator, String title, String content, String type
			
	// ,boolean promotedForExecution
	) {
		this(); // To initailize the linkedlists

		this.setInitiator(initiator);
		this.title = title;
		this.content = content;
		this.status = "opened";
		dateCreated = new Date(new java.util.Date().getTime());
		// this.promotedForExecution=promotedForExecution;
	}

	public String getTitle() {
		return title;
	}

	public void setTitle(String title) {
		this.title = title;
	}

	public String getContent() {
		return content;
	}

	public void setContent(String content) {
		this.content = content;
	}

	public Date getDateCreated() {
		return dateCreated;
	}

	public void setDateCreated(Date dateCreated) {
		this.dateCreated = dateCreated;
	}

	public Organization getOrganization() {
		return organization;
	}

	public void setOrganization(Organization organization) {
		
		this.organization = organization;
		organization.addTopic(this);
	
	}

	public List<Idea> getIdeas() {
		return  ideas;
	}

	public void setIdeas(LinkedList<Idea> ideas) {
		this.ideas = ideas;
	}

	public Eentity getEntity() {
		return entity;
	}

	public void setEntity(Eentity entity) {
		
		this.entity = entity;
		this.setOrganization(entity.getOrganization());
		entity.addTopic(this);
		
	}

	public List<Item> getItems() {
		return items;
	}

	public void setItems(List<Item> items) {
		this.items = items;
	}

	public LinkedList<Comment> getComments() {
		return (LinkedList<Comment>) comments;
	}

	public void setComments(LinkedList<Comment> comments) {
		this.comments = comments;
	}

	public LinkedList<Tag> getTags() {
		return (LinkedList<Tag>) tags;
	}

	public void setTags(LinkedList<Tag> tags) {
		this.tags = tags;
	}

	public String getStatus() {
		return this.status;
	}

	public void setStatus(String stat) {
		this.status = stat;
	}

	public void setMembers (User member){
		member.getRoleList().add(new Role(this, "Member"));
		members.add(member);
	}
	
	public void setFollowers(User follower) {
		follower.getRoleList().add(new Role(this,"Follower"));
		members.add(follower);
	}
	public boolean isSpam() {
		return spam;
	}

	public void setSpam(boolean spam) {
		this.spam = spam;
	}
	
	public LinkedList<User> getFollowers() {
		LinkedList<User> followers  = new LinkedList<User>();
		
		
		for (int i=0;i<members.size();i++)
		{
			for(int j = 0; j< members.get(i).getRoleList().size(); j++) {
				if (members.get(i).getRoleList().get(j).getTitle().equalsIgnoreCase("Follower") &&
						(members.get(i).getRoleList().get(j).getRelatedTopic() != null)
					&&	members.get(i).getRoleList().get(j).getRelatedTopic().equals(this)) {
					followers.add(members.get(i));
				}
			}
			
		}
		return followers;
	}
	
	public LinkedList<User> getContributors() {
		LinkedList<User> followers  = new LinkedList<User>();
		
		
		for (int i=0;i<members.size();i++)
		{
			for(int j = 0; j< members.get(i).getRoleList().size(); j++) {
				if (members.get(i).getRoleList().get(j).getTitle().equalsIgnoreCase("Member") &&
						(members.get(i).getRoleList().get(j).getRelatedTopic() != null)
					&&	members.get(i).getRoleList().get(j).getRelatedTopic().equals(this)) {
					followers.add(members.get(i));
				}
			}
			
		}
		return followers;
	}
	


	// set flag of promoted for execution : Author Aly Mostafa
	public void setPromoted(boolean flag) {
		promotedForExecution = flag;
	}

	public void setInitiator (User initiator){
		this.save();
		initiator.save();
		Role role = new Role (this,"Creator");
		role.save();
		initiator.getRoleList().add(role);
		role.save();
		members.add(initiator);
		initiator.addTopic(this);
	}

	public User getInitiator() {
		for (int i=0;i<members.size();i++)
		{
			for(int j = 0; j< members.get(i).getRoleList().size(); j++) {
				if (members.get(i).getRoleList().get(j).getTitle().equalsIgnoreCase("Creator") &&
						(members.get(i).getRoleList().get(j).getRelatedTopic() != null)
					&&	members.get(i).getRoleList().get(j).getRelatedTopic().equals(this)) {
				return members.get(i);
				}
			}
			
		}
		return null;
	}

	/**
	 * get all users of a Topic
	 * 
	 * @author mohamed elshikh
	 * @version 2011.0424
	 * @category C2D11
	 * @params t: Topic that i want to get all of its users
	 * @return list of all users related to the topic
	 */
	public static LinkedList<User> AllTopicUsers(Topic t) {
		LinkedList<User> users = new LinkedList<User>();
		users.add(t.getInitiator());
		for (int i = 0; i < t.getContributors().size(); i++) {
			users.add(t.getContributors().get(i));
		}
		for (int i = 0; i < t.getFollowers().size(); i++) {
			users.add(t.getFollowers().get(i));
		}
		return users;
	}

	public void setMembers(List<User> members) {
		this.members = members;
	}

	public List<User> getMembers() {
		return members;
	}

	public void addMember(User user) {
		user.addTopic(this);
		members.add(user);
	}

	public void addContributor(User user) {
		user.addTopic(this);
		getContributors().add(user);
	}

	public void addFollowers(User user) {
		user.addTopic(this);
		getFollowers().add(user);
	}

	public void addTag(Tag tag) {
		if(!has(tag)) {
			tags.add(tag);
			tag.addTopic(this);
		}
	}

	public void addIdea(Idea idea) {
		if(!has(idea)) {
			ideas.add(idea);
			idea.setTopic(this);
		}
	}

	public void addComment(Comment comment) {
		if (!has(comment)) {
			comments.add(comment);
			comment.setTopic(this);
		}
	}
	
	private boolean has(Comment comment) {
		for(int i = 0;i < comments.size();i++)
			if(comments.get(i).id == comment.id)
				return true;
		return false;
	}

	private boolean has(Tag tag) {
		for(int i = 0;i < tags.size();i++)
			if(tags.get(i).id == tag.id)
				return true;
		return false;
	}
	
	private boolean has(Idea idea) {
		for(int i = 0;i < ideas.size();i++)
			if(ideas.get(i).id == idea.id)
				return true;
		return false;
	}
	
	private boolean has(User user) {
		for(int i = 0;i < members.size();i++)
			if(members.get(i).id == user.id)
				return true;
		return false;
	}

}